home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / extbind.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  768 lines

  1. /*
  2.  * $Id: extbind.c,v 0.91 1994/02/20 00:53:17 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *   Purpose:
  26.  *     Handles external bindings. See Doc for formats specifications
  27.  *
  28.  *  Code is slightly complicated by the fact that we can not simply
  29.  *  create a double-ended pipe to do IO because we MUST guarantee
  30.  *  fseek-ablity.
  31.  */
  32. #if !defined(lint) && defined (F_ID)
  33. char *id_extb = "$Id: extbind.c,v 0.91 1994/02/20 00:53:17 zhao Pre-Release $";
  34. #endif
  35.  
  36. #include "bit.h"
  37. #include "extern.h"
  38. #include "dmalloc.h"
  39.  
  40. /*******************************************************************
  41.  * External convolution kernels
  42.  ****************************************************************{*/
  43.  
  44. /******************* Limits **********************************/
  45.  
  46. #define MAXCONV  35        /* max no. of extern matrices */
  47.  
  48. /************************************************************
  49.  * structures for external kernel and associated functions
  50.  ************************************************************/
  51. typedef struct
  52.   {
  53.       char *name;        /* name of the kernel           */
  54.       int rows, cols;        /* matrix and its order(square) */
  55.       int **m;            /* the matrix                   */
  56.   }
  57. ext_convolv_t;
  58.  
  59. /*************************************************************
  60.  * free an ext_convolve: name & matrix
  61.  *************************************************************/
  62. static void
  63. ec_free(ext_convolv_t * p)
  64. {
  65.     if (p->name)
  66.       {
  67.       free(p->name);
  68.       p->name = 0;
  69.       }
  70.     p->rows = p->cols = 0;
  71.     free_mat(p->m);
  72.     p->m = 0;
  73. }
  74.  
  75. /*************************************************************
  76.  * ext_convolve struct copy
  77.  ************************************************************/
  78.  
  79. static void
  80. ec_dup(ext_convolv_t * to, const ext_convolv_t * from)
  81. {
  82.     to->name = strdup(from->name);
  83.     to->rows = from->rows;
  84.     to->cols = from->cols;
  85.     to->m = get_mat(to->rows, to->cols, sizeof(int));
  86.     memcpy(to->m[0], from->m[0], sizeof(int) * to->rows * to->cols);
  87. }
  88.  
  89. /**************************************************************
  90.  * if two definations are identical
  91.  **************************************************************/
  92. /* rather loose, if same name and same rank, consider same */
  93. static int
  94. ec_identical(const ext_convolv_t * a, const ext_convolv_t * b)
  95. {
  96.     return (a->rows == b->rows &&
  97.         a->cols == b->cols &&
  98.         strcmp(a->name, b->name) == 0);
  99. }
  100.  
  101. /************* Variables and functions ************************/
  102.  
  103. static ext_convolv_t convolv[MAXCONV];
  104. static IPTR iptr;        /* local copy of input image ptr */
  105.  
  106. static int ec_scanner(void);
  107. static void ec_doit(long);
  108.  
  109. /*************************************************************
  110.  * The global entry point for external convolution
  111.  *************************************************************/
  112.  
  113. int
  114. do_ext_convolv(IPTR im)
  115. {
  116.     static int nkernel, action = -1;
  117.     int i;
  118.  
  119.     iptr = im;
  120.  
  121.     if (!image_ready(im, "ExtConvolv"))
  122.     return -1;
  123.  
  124.     if (!nkernel && (nkernel = ec_scanner()) <= 0)
  125.       {
  126.       help_cb(0, HELP_CONVOLV);
  127.       return -1;
  128.       }
  129.  
  130.     /* make action table */
  131.     if (action < 0)
  132.       {
  133.       action = define_action("Convolution", "convolv.hlp");
  134.  
  135.       for (i = 0; i < nkernel; i++)
  136.           addto_action(action, convolv[i].name, ec_doit);
  137.       }
  138.  
  139.     /* that is it */
  140.     do_action(action);
  141.     return 0;
  142. }
  143.  
  144. /***************************************************************
  145.  * do_ec actually does the convolution by calling img_convolve.
  146.  * do_action will invoke ec_doit.
  147.  ***************************************************************/
  148.  
  149. static void
  150. ec_doit(long p)
  151. {
  152.     ext_convolv_t *q = convolv + p;
  153.  
  154.     if (img_convolv(iptr, q->m, q->rows, q->cols, (int *) 0,
  155.             img_rect(iptr), q->name) >= 0)
  156.       {
  157.       update_image_info(iptr);
  158.       iptr->io->display(iptr, 4, 1);
  159.       }
  160. }
  161.  
  162.  
  163. /****************************************************************
  164.  * Free all ec
  165.  ****************************************************************/
  166. void
  167. free_all_ext_convolv(void)
  168. {
  169.     ext_convolv_t *ec = convolv + MAXCONV;
  170.  
  171.     while (--ec > convolv)
  172.     ec_free(ec);
  173. }
  174.  
  175. /*********************************************************************
  176.  * remove redundant entries. Need to do this because external matrices
  177.  * are loaded from SysDir and UserDir
  178.  *********************************************************************/
  179.  
  180. static int
  181. ec_uniq(void)
  182. {
  183.     static int ok, uniq = 1;    /* we have at least one uniq */
  184.     ext_convolv_t *p = convolv, *ps;
  185.     int i, found;
  186.  
  187.     if (ok)
  188.     return uniq;
  189.     p++;
  190.  
  191.     for (ps = p - 1 + MAXCONV; p < ps && p->name; p++)
  192.       {
  193.       /* search for in uniqued array */
  194.       for (i = found = 0; !found && i < uniq; i++)
  195.           found = ec_identical(p, convolv + i);
  196.  
  197.       if (!found)
  198.         {
  199.         if (convolv[i].name != p->name)    /* not the same */
  200.           {
  201.               ec_free(convolv + uniq);
  202.               ec_dup(convolv + uniq, p);
  203.               ec_free(p);
  204.           }
  205.         uniq++;
  206.         }
  207.       else
  208.         {            /* redundant */
  209.         ec_free(p);
  210.         }
  211.       }
  212.     ok = 1;
  213.  
  214.     return uniq;
  215. }
  216.  
  217.  
  218. /******* scan string for matrix: n,n,n,n,n,n *****/
  219. static int **
  220. scan_matrix(int n, char *str)
  221. {
  222.     int err = 0, c, k = 0, len = strlen(str);
  223.     int **mm = get_mat(n, n, sizeof(int)), *m, *ms;
  224.  
  225.     if (mm)
  226.       {
  227.       m = mm[0];
  228.       for (ms = m + n * n, err = k = 0; !err && m < ms && k < len; m++)
  229.         {
  230.         err = (sscanf(str + k, " %d ,%n", m, &c) < 1);
  231.         k += c;
  232.         }
  233.       }
  234.     if (err)
  235.       {
  236.       free_mat(mm);
  237.       return 0;
  238.       }
  239.     return mm;
  240. }
  241.  
  242. /****** read a external kernel defination file from stream fp ** **/
  243. #define ECFMT "@ %[^;]; %d ; %[^;];"
  244. static int
  245. ec_scanner_fp(FILE * fp, int start)
  246. {
  247.     int order = 0, sofar = start, err = 0;
  248.     char line[256], name[256], nm[256];
  249.  
  250.     while (fgets(line, sizeof(line), fp))
  251.       {
  252.       if (line[0] != '@')
  253.           continue;
  254.       err = (sscanf(line, ECFMT, name, &order, nm) < 3);
  255.  
  256.       /* skip if anything wrong */
  257.       if (err || !name[0] || order <= 0 || order > 10 || !nm[0])
  258.         {
  259.         M_warn("EXTCONV", "Bad line %s\n \tname=%s\torder=%d",
  260.                line, name, order);
  261.         }
  262.       else
  263.         {
  264.         convolv[sofar].name = strdup(name);
  265.         convolv[sofar].rows = order;
  266.         convolv[sofar].cols = order;
  267.         if ((convolv[sofar].m = scan_matrix(order, nm)))
  268.           {
  269.               sofar++;
  270.           }
  271.         else
  272.           {
  273.               M_err("", "Bad matrix: %s", nm);
  274.           }
  275.         sofar %= MAXCONV;
  276.         }
  277.       }
  278.  
  279.     /* number of correct entries read */
  280.     return sofar - start;
  281. }
  282.  
  283. /******** Read definations from UserDir and SysDir */
  284. static int
  285. ec_scanner(void)
  286. {
  287.     FILE *fp;
  288.     int total = 0;
  289.     static const char *convolvfile = "BIT_convolve";
  290.  
  291.     /* try  the system directory first */
  292.     if ((fp = get_HELPfile_fp(convolvfile, "r")))
  293.       {
  294.       total = ec_scanner_fp(fp, 0);
  295.  
  296. #ifdef MDEBUG
  297.       M_debug("ExtConvolv", "%d matrices read from %s", total, helppath);
  298. #endif
  299.  
  300.       fclose(fp);
  301.       }
  302.  
  303.     /* try user directory */
  304.     if ((fp = get_BITfile_fp(convolvfile, "r")))
  305.       {
  306.       total += ec_scanner_fp(fp, total >= 0 ? total : 0);
  307.  
  308. #ifdef MDEBUG
  309.       M_debug("ExtConvolv", "Total %d matrices read", total);
  310. #endif
  311.  
  312.       fclose(fp);
  313.       }
  314.  
  315.     /* remove reduandant definations */
  316.     if (total)
  317.       {
  318.       total = ec_uniq();
  319.       }
  320.     else
  321.       {
  322.       M_err("ExtConvolv", "error reading %s from %s", convolvfile, bitpath);
  323.       M_err("ExtConvolv", "error reading %s from %s", convolvfile, helppath);
  324.       Bark("ExtConvolv", "No valid convolution matrix found");
  325.       }
  326.     M_info("ExtConvolv", "Total %d unique matrices read", total);
  327.     return total;
  328. }
  329.  
  330.  
  331. /*****************************************************************
  332.  * END of External Convolution Kernel routine
  333.  ************************************************************}***/
  334.  
  335.  
  336.  
  337. /****************************************************************
  338.  * Handle external filters as if the following is done:
  339.  * dump | ext_filter | load
  340.  *
  341.  * the actual process is done in two steps
  342.  * 1.  external_filter > filtered_output
  343.  * 2.  load filtered_output
  344.  *
  345.  * This is still not strictly correct because what we really
  346.  * want is a 3 step process:
  347.  * 1. write currentimage > tmp
  348.  * 2. external_filter tmp > output
  349.  * 3. load output
  350.  *
  351.  * well, until someone complains
  352.  ***************************************************************/
  353.  
  354. /*************** Limits *****************************/
  355.  
  356. #define MAX_B    35        /* no. of bindings                */
  357. #define MAXFFMT  4        /* no. formats each B accepts     */
  358. #define MAXTOK   125        /* max name, label, whatever      */
  359.  
  360.  
  361. /********* Structure for bindings ****************/
  362. typedef struct
  363. {
  364.     char *title, *pname, *opt;    /* title, program, option       */
  365.     char *infmt[MAXFFMT + 1];    /* format, ppm, gif, etc        */
  366.     int in;            /* index into the img_io struct */
  367. }
  368. ext_filter_t;
  369.  
  370.  
  371. /************ Variables and functions ***********/
  372. static ext_filter_t filter[MAX_B];
  373. static char *swapfile;
  374. static char *ef_cmd;        /* current command */
  375.  
  376. extern FILE *popen(const char *, const char *);
  377. #include <signal.h>
  378. #include <setjmp.h>
  379. static jmp_buf jpipe;        /* for error recovery */
  380.  
  381. #if defined (__STRICT_ANSI__) && !defined(__sgi__)
  382. typedef void (*SIG_PF) (int,...);
  383. #endif
  384.  
  385. static SIG_PF opipe;
  386.  
  387. static int ef_scanner(void);
  388. static void ef_pipe(int);
  389. static void ef_doit(long);
  390.  
  391. /****************************************************
  392.  * Global interface for external filters
  393.  ******************************************************/
  394. int
  395. do_ext_filter(IPTR im)
  396. {
  397.     static int nfs, bindex = -1;
  398.  
  399.     iptr = im;
  400.  
  401.     if (nfs <= 0 && (nfs = ef_scanner()) <= 0)
  402.       {
  403.       help_cb(0, HELP_FILTER);
  404.       return -1;
  405.       }
  406.  
  407.     /* make the action table */
  408.     if (bindex < 0)
  409.       {
  410.       ext_filter_t *p = &filter[0], *ps;
  411.       char *label;
  412.  
  413.       bindex = define_action("ExternFilter", "filter.hlp");
  414.  
  415.       for (ps = p + nfs; p < ps; p++)
  416.         {
  417.         label = p->title ? p->title : p->pname;
  418.         if (addto_action(bindex, label, ef_doit) < 0)
  419.             M_warn("Scanner", "addto_action failed for %s", label);
  420.         }
  421.       }
  422.  
  423.     if (bindex < 0)
  424.       {
  425.       Bark("ExtFilter", "Something is wrong");
  426.       return -1;
  427.       }
  428.  
  429.     /* take over the pipe handler */
  430.  
  431.     opipe = signal(SIGPIPE, ef_pipe);
  432.     (void) setjmp(jpipe);
  433.  
  434.     /* fireworks here */
  435.     do_action(bindex);
  436.  
  437.     /* restore old handler */
  438.     (void) signal(SIGPIPE, opipe);
  439.     return 0;
  440. }
  441.  
  442. /*******************************************************************
  443.  * The beef: actual work is done here. Really wish there were a
  444.  * snprintf function which will make this routine much safer.
  445.  *******************************************************************/
  446.  
  447. static const char *pref = ".BIT";
  448. #ifdef __STRICT_ANSI__
  449. extern int pclose(FILE *);
  450. #endif
  451. static void
  452. ef_doit(long a)
  453. {
  454.     char cmd[3 * MAXTOK], *opt;
  455.     int in;
  456.     IPTR local;
  457.     ext_filter_t *p;
  458.     IMG_IO *io;
  459.  
  460.     p = filter + a;
  461.  
  462.     /* find the best match from the list of needed formats */
  463.     if ((in = best_format(iptr, p->infmt)) < 0)
  464.       {
  465.       Bark("ExtFilter", "BadFmt _%s_", p->infmt[0] ? p->infmt[0] : "None");
  466.       return;
  467.       }
  468.  
  469.     io = img_io + in;
  470.  
  471.     /* convert to the needed types if different */
  472.     if (io->type != T_FLEX && iptr->type != io->type &&
  473.     img_convert_type(iptr, io->type))
  474.     return;
  475.  
  476.  
  477.     if (!(swapfile = get_tmpf(pref)))
  478.       {
  479.       Bark("ExtBind", "unable to create tmpfile");
  480.       return;
  481.       }
  482.  
  483.     /* check if interactive command line options */
  484.     if ((opt = p->opt) && strcmp(opt, "?") == 0)
  485.       {
  486.       const char *q;
  487.       sprintf(cmd, "Options for %s", p->pname);
  488.       if ((q = getstring(cmd, "", 1)))
  489.           opt = strdup(q);
  490.       check_emergency();
  491.       }
  492.  
  493.     /* generate the shell command on the fly */
  494.     ef_cmd = p->pname;
  495.     sprintf(cmd, "%s %s > %s", p->pname, opt ? opt : "", swapfile);
  496.  
  497.     if (opt != p->opt)
  498.     free(opt);
  499.  
  500.     M_info("pipe", "executing %s", cmd);
  501.  
  502.     if (!(iptr->fp = popen(cmd, "w")))
  503.     return;
  504.  
  505.     /* need to save the original filename before dump */
  506.     Strncpy(cmd, iptr->ifile, sizeof(cmd));
  507.     io->dump(iptr);
  508.  
  509.     /**** wait until pipe closes ***************/
  510.  
  511.     show_busy("PleaseWait ...");
  512.     (void) pclose(iptr->fp);
  513.     end_busy();
  514.  
  515.     /******* So far so good, try  to load it ****/
  516.  
  517.     set_current_window(win_id);
  518.  
  519.     /* service Q first before doing anything else */
  520.     check_emergency();
  521.  
  522.     /* load the image and replace the old one if successful * */
  523.     if ((local = load_image(swapfile)))
  524.       {                /* ok */
  525.       free_image_mem(iptr);    /* must not free iptr itself */
  526.       memcpy(iptr, local, sizeof(*iptr));
  527.       free(local);
  528.       }
  529.  
  530.     del_tmpf(swapfile);
  531.     Strncpy(iptr->ifile, cmd, TC_FL);
  532.     update_filename(iptr->ifile);
  533.     iptr->io->display(iptr, 3, 1);
  534. }
  535.  
  536. /************** Free an ext binding ***************/
  537. static void
  538. ef_free(ext_filter_t * p)
  539. {
  540.     char **q = p->infmt;
  541.  
  542.     Free(p->title);
  543.     Free(p->pname);
  544.     Free(p->opt);
  545.  
  546.     while (*q)
  547.       {
  548.       free(*q);
  549.       *q = 0;
  550.       q++;
  551.       }
  552. }
  553.  
  554. /************** Free all ext binding ***************/
  555. void
  556. free_all_ext_filter(void)
  557. {
  558.     ext_filter_t *p = filter + MAX_B;
  559.  
  560.     while (--p >= filter)
  561.     ef_free(p);
  562. }
  563.  
  564.  
  565. /******* make a copy of the ext_filter **************/
  566.  
  567. static void
  568. ef_dup(ext_filter_t * to, ext_filter_t * from)
  569. {
  570.     char **tof, **fromf;
  571.  
  572.     to->title = strdup(from->title);
  573.     to->pname = strdup(from->pname);
  574.     to->opt = strdup(from->opt);
  575.     fromf = from->infmt;
  576.     tof = to->infmt;
  577.  
  578.     while (*fromf)
  579.       {
  580.       *tof = strdup(*fromf);
  581.       fromf++;
  582.       tof++;
  583.       }
  584.     *tof = 0;
  585. }
  586.  
  587. /******************************************************************
  588.  * remove redundant definitions. we need to do this because BIT loads
  589.  * definitions from sys dir and user dir
  590.  *****************************************************************/
  591. static int
  592. ef_uniq(void)
  593. {
  594.     ext_filter_t *p = filter, *ps;
  595.     static int uniq = 1;    /* will at least have on uniq entry */
  596.     static int ok;
  597.     int i, found;
  598.  
  599.     if (ok)
  600.     return uniq;
  601.  
  602.     p++;
  603.     for (ps = p + MAX_B - 1; p < ps && p->title; p++)
  604.       {
  605.       /* search thru uniq so far */
  606.       for (i = found = 0; !found && i < uniq; i++)
  607.           found = strcmp(p->title, filter[i].title) == 0 &&
  608.           strcmp(p->pname, filter[i].pname) == 0;
  609.  
  610.       if (!found)
  611.         {            /* move it */
  612.         if (filter[uniq].title != p->title)
  613.           {
  614.               ef_free(filter + uniq);
  615.               ef_dup(filter + uniq, p);
  616.               ef_free(p);
  617.           }
  618.         ++uniq;
  619.         }
  620.       else
  621.         {
  622.         ef_free(p);
  623.         }
  624.       }
  625.     ok = 1;
  626.     return uniq;
  627. }
  628.  
  629.  
  630. #define EFFMT  "@%[^;];%[^;];%[^;];%[^;];%n"
  631. static int
  632. ef_scanner_fp(FILE * fp, int start)
  633. {
  634.     char line[MAXTOK], blab[MAXTOK], prgm[MAXTOK];
  635.     char opt[MAXTOK], inf[MAXTOK];
  636.     ext_filter_t *p;
  637.     int err = 0, in, n, kfmt, sofar = start;
  638.  
  639.  
  640.     while (fgets(line, MAXTOK, fp))
  641.       {
  642.       if (line[0] != '@')
  643.           continue;
  644.       err = (sscanf(line, EFFMT, blab, prgm, opt, inf, &n) < 4);
  645.  
  646.       space_de(de_space(prgm));
  647.       space_de(de_space(blab));
  648.       space_de(de_space(opt));
  649.       space_de(de_space(inf));
  650.  
  651. #ifdef MTRACE
  652.       M_trace("EB", "L=%s P=%s O=%s F=%s", blab, prgm, opt, inf);
  653. #endif
  654.       err = err || (!prgm[0] || !inf[0]);
  655.  
  656.       if (!err)
  657.         {
  658.         p = &filter[sofar];    /* sofar will never out of bounds */
  659.         p->title = strdup(blab[0] ? blab : prgm);
  660.         p->pname = strdup(prgm);
  661.         p->opt = opt[0] ? strdup(opt) : 0;
  662.         p->infmt[0] = strdup(inf);
  663.  
  664.         /* now get alternate formats */
  665.         err = 0;
  666.         kfmt = 1;
  667.         while (!err && kfmt < MAXFFMT && n < strlen(line) - 1)
  668.           {
  669.               err = sscanf(line + n, "%[^;];%n", inf, &in) <= 0;
  670.               space_de(de_space(inf));
  671.               n += in;
  672.               if (!err)
  673.             {
  674.                 p->infmt[kfmt] = strdup(inf);
  675.                 kfmt++;
  676.             }
  677.           }
  678.         /* important. Best_format depends on this */
  679.         p->infmt[MAXFFMT] = 0;
  680.         sofar++;
  681.         sofar %= MAX_B;
  682.         }
  683.       else
  684.         {
  685.         M_warn("EB", "bad line %s\n\ttitle: %s", line, blab);
  686.         M_warn("EB", "\tpname:%s\n\t  opt:%s\t  inf:%s",
  687.                prgm, opt, inf);
  688.         }
  689.       blab[0] = prgm[0] = opt[0] = inf[0] = '\0';
  690.       }
  691.     return sofar - start;
  692. }
  693.  
  694. static int
  695. ef_scanner(void)
  696. {
  697.     int sofar = 0;
  698.     static const char *filterfile = "BIT_filters";
  699.     FILE *fp;
  700.  
  701. #ifdef MTRACE
  702.     M_trace("EF_scanner", "Entering");
  703. #endif
  704.  
  705.     if ((fp = get_HELPfile_fp(filterfile, "r")))
  706.       {
  707.       sofar = ef_scanner_fp(fp, 0);
  708.       (void) fclose(fp);
  709.       M_info("ExtFilter", "%d bindings read from %s", sofar, helppath);
  710.       }
  711.  
  712.     if ((fp = get_BITfile_fp(filterfile, "r")))
  713.       {
  714.       sofar += ef_scanner_fp(fp, sofar >= 0 ? sofar : 0);
  715.       (void) fclose(fp);
  716.       M_info("ExtFilter", "total %d bindings read from", sofar, bitpath);
  717.       }
  718. #ifdef MTRACE
  719.     M_trace("EF_scanner", "Exit");
  720. #endif
  721.  
  722.     /* check to make sure there are no repeat entries */
  723.     if (sofar)
  724.       {
  725.       sofar = ef_uniq();
  726.       }
  727.     else
  728.       {
  729.       M_err("ExtFilter", "error reading %s from %s", filterfile, bitpath);
  730.       M_err("ExtFilter", "error reading %s from %s", filterfile, helppath);
  731.       Bark("ExtFilter", "No valid filters defined");
  732.       }
  733.     M_info("ExtFilter", "Total %d unique bindings read", sofar);
  734.     return sofar;
  735. }
  736.  
  737.  
  738. /*************************************************************
  739.  * All errors during execution of the filter will end-up here
  740.  ************************************************************/
  741.  
  742. static void
  743. ef_pipe(int sig)
  744. {
  745.  
  746. #ifdef MTRACE
  747.     M_trace("EB_pipe", "Entering");
  748. #endif
  749.  
  750.     if (sig != SIGPIPE)
  751.       {
  752.       Bark("EB_pipe", "Something is very wrong");
  753.       clean_up();
  754.       }
  755.  
  756.     Bark("ExtBind", "%s: Something is wrong in pipe", ef_cmd);
  757.  
  758.     remove_progress_report();
  759.     fl_activate_all_forms();
  760.     signal(SIGPIPE, ef_pipe);
  761.     del_tmpf(swapfile);
  762.  
  763. #ifdef MTRACE
  764.     M_trace("EB_pipe", "Exit");
  765. #endif
  766.     longjmp(jpipe, 1);
  767. }
  768.